package com.nit.bike.service.basic.impl;

import com.alibaba.fastjson.JSONObject;
import com.nit.bike.dto.utils.OpResultDTO;
import com.nit.bike.mapper.basic.StatisticsMapper;
import com.nit.bike.service.basic.StatisticsService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

@Service
public class StatisticsServiceImpl implements StatisticsService {
    @Resource
    private StatisticsMapper mapper;

    @Override
    public OpResultDTO statsUser(JSONObject json) throws Exception {
        OpResultDTO op = new OpResultDTO();
        op.setMessage("error");
        JSONObject res = new JSONObject();
        List<String[]> ranges = getDateRange(json);
        if (ranges == null) {
            op.setResult("参数有误");
            return op;
        }
        res.put("total", mapper.getUserTotal());
        List<JSONObject> increase = new ArrayList<>(ranges.size());
        for (int i = 0; i < ranges.size(); i++) {
            String[] range = ranges.get(i);
            JSONObject item = new JSONObject();
            item.put("x", i);
            item.put("y", mapper.getUserIncrease(range[0], range[1]));
            increase.add(item);
        }
        res.put("increase", increase);
        op.setMessage("success");
        op.setResult(res);
        return op;
    }

    @Override
    public OpResultDTO bikeTotal(JSONObject json) throws Exception {
        OpResultDTO op = new OpResultDTO();
        op.setMessage("success");
        op.setResult(mapper.getBikeStats());
        return op;
    }

    @Override
    public OpResultDTO payTotal(JSONObject json) throws Exception {
        OpResultDTO op = new OpResultDTO();
        op.setMessage("success");
        op.setResult(mapper.getPayTotal());
        return op;
    }

    @Override
    public OpResultDTO duringTotal(JSONObject json) throws Exception {
        OpResultDTO op = new OpResultDTO();
        op.setMessage("success");
        op.setResult(mapper.getDuringTotal());
        return op;
    }

    @Override
    public OpResultDTO duringAndCost(JSONObject json) throws Exception {
        OpResultDTO op = new OpResultDTO();
        op.setMessage("error");
        List<String[]> ranges = getDateRange(json);
        if (ranges == null) {
            op.setResult("参数有误");
            return op;
        }
        List<JSONObject> res = new ArrayList<>(ranges.size());
        for (int i = 0; i < ranges.size(); i++) {
            String[] range = ranges.get(i);
            JSONObject item = mapper.getDuringAndCost(range[0], range[1]);
            if (item == null) {
                item = new JSONObject();
                item.put("during", 0);
                item.put("cost", BigDecimal.ZERO);
            }
            item.put("index", i);
            res.add(item);
        }
        op.setMessage("success");
        op.setResult(res);
        return op;
    }

    /**
     * 根据类型获取时间段 YYYY-MM-DD
     * 1 今天0点到当前时间，一小时一个时间段
     * 2 本周一到明天，一天一个时间段
     * 3 本月1号到明天，一天一个时间段
     * 4 今年1月到下一月，一月一个时间段
     * 返回字符串第一个开始时间，第二个结束时间
     * 例如现在 2021-05-30 02:30，查询1会得到如下结果
     * [['2021-05-30 00','2021-05-30 01'],['2021-05-30 01', '2021-05-30 02'],['2021-05-30 02', '2021-05-30 03']]
     */
    public static List<String[]> getDateRange(JSONObject json) {
        Integer type;
        if (json == null) {
            type = 3;
        } else {
            type = json.getInteger("type");
            if (type == null) {
                type = 3;
            } else if (type > 3 || type < 0) {
                return null;
            }
        }
        List<String[]> res = new ArrayList<>();
        String[] range;
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        switch (type) {
            case 0:
                // 单日
                int hourOfDay = calendar.get(Calendar.HOUR_OF_DAY);
                sdf = new SimpleDateFormat("yyyy-MM-dd HH");
                calendar.set(Calendar.HOUR_OF_DAY, 0);
                for (int i = 0; i <= hourOfDay; i++) {
                    range = new String[2];
                    range[0] = sdf.format(calendar.getTime());
                    calendar.add(Calendar.HOUR, 1);
                    range[1] = sdf.format(calendar.getTime());
                    res.add(range);
                }
                break;
            case 1:
                // 本周
                int dayOfWeek = (calendar.get(Calendar.DAY_OF_WEEK) + 5) % 7;
                calendar.add(Calendar.DATE, -dayOfWeek);
                for (int i = 0; i <= dayOfWeek; i++) {
                    range = new String[2];
                    range[0] = sdf.format(calendar.getTime());
                    calendar.add(Calendar.DATE, 1);
                    range[1] = sdf.format(calendar.getTime());
                    res.add(range);
                }
                break;
            case 2:
                // 本月
                int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH) - 1;
                calendar.add(Calendar.DATE, -dayOfMonth);
                for (int i = 0; i <= dayOfMonth; i++) {
                    range = new String[2];
                    range[0] = sdf.format(calendar.getTime());
                    calendar.add(Calendar.DATE, 1);
                    range[1] = sdf.format(calendar.getTime());
                    res.add(range);
                }
                break;
            case 3:
                // 今年
                int month = calendar.get(Calendar.MONTH);
                calendar.set(Calendar.MONTH, 0);
                calendar.set(Calendar.DAY_OF_MONTH, 1);
                for (int i = 0; i <= month; i++) {
                    range = new String[2];
                    range[0] = sdf.format(calendar.getTime());
                    calendar.add(Calendar.MONTH, 1);
                    range[1] = sdf.format(calendar.getTime());
                    res.add(range);
                }
                break;
        }
        return res;
    }
}
